package com.ruicar.afs.cloud.basic.sync;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.basic.common.entity.*;
import com.ruicar.afs.cloud.basic.common.service.*;
import com.ruicar.afs.cloud.basic.proceeds.mq.dto.*;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.uid.UidGenerator;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

/**
 * @author: Lee
 * @date: 2020/5/11 19:39
 * @description: 贷前数据同步-客户类信息
 */
@AllArgsConstructor
@Component
@Slf4j
public class ApplyLoanDataCustSubHandler{

	private final BasicCustBaseInfoService basicCustBaseInfoService;
	private final BasicCustPersonalDetailService basicCustPersonalDetailService;
	private final BasicCustContactDetailsService basicCustContactDetailsService;
	private final BasicCustAddressDetailsService basicCustAddressDetailsService;
	private final BasicContractCustRelationService custRelationService;
	private final BasicCustContactsService basicCustContactsService;
	private final UidGenerator uidGenerator;

	/*
	 * 合同激活客户类信息存储
	 */
	public void saveOrUpdateCust (ApplyLoanDataMessage entity){

		//保存客户基本信息表
		Map<String, String> custMapping = this.saveCustBaseInfo(entity);
		//保存个人客户详细信息 TODO 公司客户如何处理 余思俊
		saveCustPersonalDetail(entity, custMapping);
		//客户关联关系信息存储
		saveCustRelation(entity, custMapping);
		//合同客户联系方式存储(含变更)
		saveCustContactDetails(entity, custMapping);
		//合同联系地址存储(含变更)
		saveCustAddressDetails(entity, custMapping);
		//合同联系人信息存储
	}
	/**
	 * * 客户类信息存储客户基本信息存储
	 */
	public Map<String, String> saveCustBaseInfo (ApplyLoanDataMessage entity){

		ContractMainInfoDTO mainInfoDTO = entity.getMainInfo();
		List<ContractCustBaseInfoDTO> baseInfoDtoList = entity.getBaseInfo();

		if (CollectionUtils.isEmpty(baseInfoDtoList)) {
			throw new AfsBaseException(MessageFormat.format("未找到合同编号为:[{0}]的客户基本信息", mainInfoDTO.getContractNo()));
		}
		//从报文中获取客户信息
		List<BasicCustBaseInfo> baseInfoList = (List<BasicCustBaseInfo>) ApplyLoanDataProcessor.converBean(baseInfoDtoList, BasicCustBaseInfo.class);
		Map<String, String> custMapping = new HashMap<>();
		for (BasicCustBaseInfo custBaiseInfo : baseInfoList) {
			//根据证件号码、证件类型从数据库获取客户信息
			List<BasicCustBaseInfo> list = basicCustBaseInfoService.list(Wrappers.<BasicCustBaseInfo>lambdaQuery()
					.eq(BasicCustBaseInfo::getCertType, custBaiseInfo.getCertType())
					.eq(BasicCustBaseInfo::getCertNo, custBaiseInfo.getCertNo()));
			if (EmptyUtils.isNotEmpty(list)) {
				//系统中已存在存该证件号的客户，则直接更新相关字段
				BasicCustBaseInfo existBaseInfo = list.get(0);
				BeanUtils.copyProperties(custBaiseInfo, existBaseInfo,"id","custNo");
				basicCustBaseInfoService.updateById(existBaseInfo);
				//系统中已存在此客户，则： map的key是报文中客户信息的客户号，value是系统中原有客户信息的客户号
				custMapping.put(custBaiseInfo.getCustNo(), existBaseInfo.getCustNo());
			} else {
				//新客户，生成新的记录使用新的客户号
				String custNo = custBaiseInfo.getCustNo();
				custBaiseInfo.setId(null);
				custBaiseInfo.setCustNo(String.valueOf(uidGenerator.getUID()));
				basicCustBaseInfoService.save(custBaiseInfo);
				//系统中无此客户，则： map的key是报文中客户信息的客户号，value也是报文中客户信息的客户号
				custMapping.put(custNo, custBaiseInfo.getCustNo());
			}
		}
		return custMapping;
	}
	/**
	 * * 客户类信息存储客户关联关系信息存储
	 */
	public void saveCustRelation (ApplyLoanDataMessage entity, Map < String, String > custMapping){
	ContractMainInfoDTO mainInfoDTO = entity.getMainInfo();
	List<ContractContractCustRelationDTO> relationDtoList = entity.getCustRelation();
	if (CollectionUtils.isEmpty(relationDtoList)) {
		throw new AfsBaseException(MessageFormat.format("未找到合同编号为:[{0}]的客户关联信息", mainInfoDTO.getContractNo()));
	}

	relationDtoList = relationDtoList.stream().map(s -> {
		s.setCustNo(custMapping.get(s.getCustNo()));
		return s;
	}).collect(Collectors.toList());

	List<BasicContractCustRelation> relationList = (List<BasicContractCustRelation>) ApplyLoanDataProcessor
			.converBean(relationDtoList, BasicContractCustRelation.class);

	custRelationService.saveOrUpdateBatch(relationList);
}
	/**
	 * * 客户类信息存储个人客户详细信息存储
	 */
	public void saveCustPersonalDetail (ApplyLoanDataMessage entity, Map < String, String > custMapping){
	List<ContractCustPersonalDetailDTO> personalDetail = entity.getPersonalDetail();

	if (!ObjectUtils.isEmpty(personalDetail)) {
		BasicCustPersonalDetail currentPersonalDetail = null;
		BasicCustPersonalDetail existPersonalDetail = null;
		for (ContractCustPersonalDetailDTO personalDetails : personalDetail) {
			currentPersonalDetail = (BasicCustPersonalDetail) ApplyLoanDataProcessor.converBean(personalDetails, BasicCustPersonalDetail.class);
			List<BasicCustPersonalDetail> list = basicCustPersonalDetailService.list(Wrappers.<BasicCustPersonalDetail>lambdaQuery()
					.eq(BasicCustPersonalDetail::getCustNo, custMapping.get(personalDetails.getCustNo())));
			if (EmptyUtils.isNotEmpty(list)) {
				existPersonalDetail = list.get(0);
				BeanUtils.copyProperties(currentPersonalDetail, existPersonalDetail);
				basicCustPersonalDetailService.updateById(existPersonalDetail);
			} else {
				currentPersonalDetail.setId(null);
				currentPersonalDetail.setCustNo(custMapping.get(personalDetails.getCustNo()));
				basicCustPersonalDetailService.save(currentPersonalDetail);
			}
		}

	}

}
	/**
	 * * 客户类信息存储客户联系方式存储(含变更) 未优化  TODO 李阳处理
	 */
	public void saveCustContactDetails (ApplyLoanDataMessage entity, Map < String, String > custMapping){
		// 合同客户联系方式begin
		List<ContractCustContactDetailsDTO> listCustContractDto = entity.getCustContractDetail();
		if (ObjectUtils.isEmpty(listCustContractDto)) {
			throw new AfsBaseException("客户联系方式信息表为空");
		}
		Map<String, List<ContractCustContactDetailsDTO>> contractDetailsMap = listCustContractDto.stream()
			.collect(Collectors.groupingBy(ContractCustContactDetailsDTO::getCustNo));
		for (Entry<String, String> entry : custMapping.entrySet()) {
			List<ContractCustContactDetailsDTO> detailsDto = contractDetailsMap.get(entry.getKey());
			if (ObjectUtils.isEmpty(detailsDto)) {
				log.warn("未找到客户号为【{0}】的联系方式信息", entry.getKey());
				continue;
			}
			for (ContractCustContactDetailsDTO dto : detailsDto) {

				BasicCustContactDetails newDetails = (BasicCustContactDetails) ApplyLoanDataProcessor.converBean(dto,
						BasicCustContactDetails.class);
				BasicCustContactDetails dbDetails = basicCustContactDetailsService.getOne(Wrappers.<BasicCustContactDetails>lambdaQuery()
						.eq(BasicCustContactDetails::getCustNo, entry.getValue())
						.eq(BasicCustContactDetails::getContactType, dto.getContactType()));
				//通过客户号、联系方式类型查询，如果查询到数据，说明之前系统中已存在此客户的该联系方式
				if(EmptyUtils.isNotEmpty(dbDetails)){
					//判断此次传入的联系方式与之前系统中存在的联系方式是否一致，不一致需要将数据存入变更信息表
					if (EmptyUtils.isNotEmpty(dbDetails.getContactNo()) && !dbDetails.getContactNo().equalsIgnoreCase(dto.getContactNo())) {
						//step 1 更新客户联系方式信息
						dbDetails.setContactNo(newDetails.getContactNo());
						basicCustContactDetailsService.updateById(dbDetails);
						//step 2 向manage服务的联系方式变更相关表同步数据
						// 联系号码不一致 要走变更
	//						CustChangeApplyDto applyDto = new CustChangeApplyDto();
	//						applyDto.setApplyNo(mainInfo.getApplyNo());
	//						applyDto.setBusinessSource(BusinessSourceEnum.BUSINESS_PEOPLE);
	//						applyDto.setDataSource(DataSourceEnum.manyKinds);
	//						BasicCustBaseInfo custBaseInfo = map.get(s.getCustNo());
	//						applyDto.setCustName(custBaseInfo.getCustName());
	//						applyDto.setCertNo(custBaseInfo.getCertNo());
	//						applyDto.setChangeSubject(relationMap.get(custBaseInfo.getCustNo()).getCustRole());
	//						applyDto.setChangType(ContactChangeTypeEnum.PHONE);
	//						applyDto.setOldPhone(contract.getContactNo());
	//						applyDto.setNewPhone(s.getContactNo());
	//						custChangeFeign.saveCustChangeApply(applyDto);
					}
				}else{
					//没有查询到联系方式数据，则新增
					newDetails.setCustNo(entry.getValue());
					basicCustContactDetailsService.save(newDetails);
				}
			}
		}
	}

	/**
	 * * 客户类信息存储联系地址存储(含变更) 未优化  TODO 李阳处理
	 */
	public void saveCustAddressDetails (ApplyLoanDataMessage entity, Map < String, String > custMapping){
	// 联系地址信息表
	List<ContractCustAddressDetailsDTO> addressDetailsList = entity.getAddressDetail();

	if (ObjectUtils.isEmpty(addressDetailsList)) {
		throw new AfsBaseException("客户联系地址信息表为空");
	}

	Map<String, List<ContractCustAddressDetailsDTO>> addressDetailsMap = addressDetailsList.stream()
			.collect(Collectors.groupingBy(ContractCustAddressDetailsDTO::getCustNo));

	for (Entry<String, String> entry : custMapping.entrySet()) {
		// 联系地址begin
		List<ContractCustAddressDetailsDTO> addressDetailList = addressDetailsMap.get(entry.getKey());
		if (ObjectUtils.isEmpty(addressDetailList)) {
			throw new AfsBaseException(MessageFormat.format("未找到客户号为【{0}】的联系地址信息", entry.getKey()));
		}
		for (ContractCustAddressDetailsDTO dto : addressDetailList) {

			BasicCustAddressDetails newDetails = (BasicCustAddressDetails) ApplyLoanDataProcessor.converBean(dto,
					BasicCustAddressDetails.class);
			BasicCustAddressDetails dbAddressDetails = basicCustAddressDetailsService.getOne(Wrappers
					.<BasicCustAddressDetails>lambdaQuery().eq(BasicCustAddressDetails::getCustNo, entry.getValue())
					.eq(BasicCustAddressDetails::getAddressType, dto.getAddressType()));
			//通过客户号、联系方式类型查询，如果查询到数据，说明之前系统中已存在此客户的该联系方式
			if(EmptyUtils.isNotEmpty(dbAddressDetails)){
				//地址变化需要向变更表插入数据
				if ((EmptyUtils.isNotEmpty(dbAddressDetails.getProvince()) && !dbAddressDetails.getProvince().equalsIgnoreCase(dto.getProvince()))
					|| (EmptyUtils.isNotEmpty(dbAddressDetails.getCity()) && !dbAddressDetails.getCity().equalsIgnoreCase(dto.getCity()))
					|| (EmptyUtils.isNotEmpty(dbAddressDetails.getCounty()) && !dbAddressDetails.getCounty().equalsIgnoreCase(dto.getCounty()))
					|| (EmptyUtils.isNotEmpty(dbAddressDetails.getStreet()) && !dbAddressDetails.getStreet().equalsIgnoreCase(dto.getStreet()))
					|| (EmptyUtils.isNotEmpty(dbAddressDetails.getAddress()) && !dbAddressDetails.getAddress().equalsIgnoreCase(dto.getAddress()))) {
					//step1 更新表数据
					newDetails.setId(dbAddressDetails.getId());
					newDetails.setCustNo(entry.getValue());
					basicCustAddressDetailsService.updateById(newDetails);
					//step2 向manage表查询变更的数据

//					CustChangeApplyDto applyDto = new CustChangeApplyDto();
//						switch (s.getAddressType()) {
//						case WORK:
//							applyDto.setOldWorkAddress(basicAddress.getAddress());
//							applyDto.setNewWorkAddress(s.getAddress());
//							break;
//						case HOME:
//							applyDto.setOldHomeAddress(basicAddress.getAddress());
//							applyDto.setNewHomeAddress(s.getAddress());
//							break;
//						case LIVE:
//							break;
//						default:
//							break;
//						}
//
//						basicAddress.setProvince(s.getProvince());
//						basicAddress.setCity(s.getCity());
//						basicAddress.setCounty(s.getCounty());
//						basicAddress.setCounty(s.getCounty());
//						basicAddress.setAddress(s.getAddress());
//						basicAddress.setGbCode(s.getGbCode());
//						basicAddress.setPostalCode(s.getPostalCode());
//						basicAddress.setIsDefault(s.getIsDefault());
//						basicCustAddressDetailsService.saveOrUpdate(basicAddress);
//
//						applyDto.setCustNo(basicAddress.getCustNo());
//						applyDto.setContractNo(mainInfo.getContractNo());
//						applyDto.setApplyNo(mainInfo.getApplyNo());
//						applyDto.setDataSource(DataSourceEnum.manyKinds);
//						applyDto.setChangeSubject(relationMap.get(basicAddress.getCustNo()).getCustRole());
//						applyDto.setChangType(ContactChangeTypeEnum.ADDRESS);
//						custChangeFeign.saveCustChangeApply(applyDto);

				}
			}else{
				newDetails.setCustNo(entry.getValue());
				basicCustAddressDetailsService.save(newDetails);
			}

		}
		// 联系地址end
	}
}
	/**
	 * * 客户类信息存储联系人信息存储
	 */
	public void saveCustContacts (ApplyLoanDataMessage entity, Map < String, String > custMapping){
		List<ContractCustContactsDTO> bsicCustContactsList = entity.getBsicCustContacts();
		if (!ObjectUtils.isEmpty(bsicCustContactsList)) {
			List<BasicCustContacts> bsicCustContacts = (List<BasicCustContacts>) ApplyLoanDataProcessor
					.converBean(bsicCustContactsList, BasicCustContacts.class);
			basicCustContactsService.saveBatch(bsicCustContacts);
		}
	}
}
